package main;

import Scenery.BaseBuilder;
import Scenery.Map.MapControl;
import Scenery.Map.MapControl;
import Scenery.Thing.Things.TreeEntity;
import Scenery.Thing.Weapons.Weapons.Axe;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.input.ChaseCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.light.PointLight;
import com.jme3.light.SpotLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.CartoonEdgeFilter;
import com.jme3.renderer.Caps;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Quad;
import com.jme3.ui.Picture;
import main.Events.EventHandler;
import main.Gui.DisplaySign;
import main.Gui.HUD;
import main.Memory.Memory;
import main.Memory.Sound;

/**
 * 
 * @author Ziden
 * 
 */

public class Main extends GameApp implements ActionListener {

    private static Main handler = null;
    public static Main getHandler() { return handler; }
    
    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }
    
    Keys IO = new Keys();
    Node mouseNode = new Node("MouseNode");
    private BulletAppState bulletAppState;
    public static MapControl mapControl;
    private RoundCamera myCamera;
    Node scene = new Node("Scene");
    private MouseInputListener mouse;
    private FilterPostProcessor fpp;
    HUD hud = new HUD();
    DisplaySign signs = new DisplaySign();
    PointLight pl = new PointLight();
    SpotLight sl = new SpotLight();
    EventHandler eventHandler;
    Geometry debug;
    
    @Override
    public void simpleInitApp() {
        handler = this;
        
        Sound.loadSounds();
        
        // apply physics state
        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
        eventHandler = new EventHandler();
        // initialize gui
        hud.initHud(assetManager, guiNode);
        signs.initHud(assetManager, guiNode);
        
        // handle maps and objects/characters on it
        mapControl = new MapControl(new BaseBuilder(assetManager, bulletAppState.getPhysicsSpace()));
        mapControl.makeTestMap();
        
        // add the character physics to space
        bulletAppState.getPhysicsSpace().add(mapControl.getDude().getControl());
        
        //set camera
        myCamera = new RoundCamera(cam, mapControl.getDude());

        //disable the default 1st-person flyCam (don't forget this!!)
        //flyCam.setEnabled(false);

        AmbientLight al = new AmbientLight();
        al.setColor(ColorRGBA.White.mult(4));
        rootNode.addLight(al);

       // lights
       // pl.setColor(ColorRGBA.White);
       // pl.setRadius(25f);
       // rootNode.addLight(pl);
        
       DirectionalLight sun = new DirectionalLight();
       sun.setDirection(new Vector3f(-0.5f,-5,-0.5f));
       sun.setColor(ColorRGBA.Gray);
       rootNode.addLight(sun); 
        
        sl.setDirection(new Vector3f(1,0,1));  // direction
        sl.setPosition(new Vector3f(0,2,0));
        sl.setSpotInnerAngle(25f); // inner light cone (maximum)
        sl.setSpotOuterAngle(58f); // outer light cone (edge of the light)
        sl.setSpotRange(35f);      // distance
        sl.setColor(ColorRGBA.White.mult(2.3f));
        //rootNode.addLight(sl);
        
        inputManager.addMapping("MOVE.6",new KeyTrigger(KeyInput.KEY_D));
        inputManager.addListener(this, "MOVE.6");
        
        inputManager.addMapping("MOVE.4",new KeyTrigger(KeyInput.KEY_A));
        inputManager.addListener(this, "MOVE.4");
        
        inputManager.addMapping("MOVE.8",new KeyTrigger(KeyInput.KEY_W));
        inputManager.addListener(this, "MOVE.8");
        
        inputManager.addMapping("MOVE.2",new KeyTrigger(KeyInput.KEY_S));
        inputManager.addListener(this, "MOVE.2");
        
        inputManager.addMapping("MOVE.7",new KeyTrigger(KeyInput.KEY_Q));
        inputManager.addListener(this, "MOVE.7");
        
        inputManager.addMapping("MOVE.9",new KeyTrigger(KeyInput.KEY_E));
        inputManager.addListener(this, "MOVE.9");
        
        mouse = new MouseInputListener(cam, mapControl.getMap().getRootMapNode(), assetManager, settings, mouseNode);
        inputManager.addRawInputListener(mouse);
        inputManager.setCursorVisible(true);
        rootNode.attachChild(mouseNode);

        //TreeEntity tree = new TreeEntity();
        //mapControl.getMap().getRootMapNode().attachChild(tree.getEntityMasterNode());
        mapControl.addEntity(new TreeEntity(), new Vector3f(1,0,-1));
        
        
        scene.attachChild(mapControl.getDude().getMasterNode());
        scene.attachChild(mapControl.getMap().getRootMapNode());
        
        rootNode.attachChild(scene);
        
        mapControl.getDude().equipWeapon(new Axe());
        
        //debug = BaseBuilder.makeBaseStone(0, 0, 0);
        //rootNode.attachChild(debug);
    }

    public void tick() {
        
    }
    
    public Geometry debugShape(Mesh shape, ColorRGBA color){
  Geometry g = new Geometry("coordinate axis", shape);
  Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
  mat.getAdditionalRenderState().setWireframe(true);
  mat.setColor("Color", color);
  g.setMaterial(mat);
  g.setLocalTranslation(0,10,0);
  rootNode.attachChild(g);
  return g;
}
    
    public static float globalTpf = 0;
    
    public float getAbstractTpf(float tpf) {
        return tpf / 0.015992543f;
    }
    
    @Override
    public void simpleUpdate(float tpf) {
        globalTpf = getAbstractTpf(tpf);
        if(mouse.clicked) {
            mouse.clicked = false;
            if(mouse.getClickedObject()!=null) {
                mapControl.click(mouse.getClickedObject());
                mouse.resetObject();
            }
        }
        
        eventHandler.processEvents();
        
        mapControl.getDude().setLookDirection(myCamera.getAngle()-90, mouse.getAngleFromPointer());
        moveDudeAndCamera();
        mapControl.getDude().positionTick();
        mapControl.getDude().checkDeath();
        sl.setPosition(mapControl.getDude().getControl().getPhysicsLocation().add(0,5,0));
        sl.setDirection(mapControl.getDude().getLookDir().subtract(0,2,0)); 
        if(mapControl.getDude().getReadingSignId()!=null) {
            signs.display(mapControl.getDude().getReadingSignId(), guiFont);
        }
        
        
        
       // pl.setPosition(mapControl.getDude().getMasterNode().getLocalTranslation().add(new Vector3f(0, 0, 0)));
       // sl.setPosition(mapControl.getDude().getMasterNode().getLocalTranslation().add(new Vector3f(0, 0, 0)));
       // sl.setDirection(mapControl.getDude().getHeadNode().getLocalRotation().getRotationColumn(1));
    }

    public void moveDudeAndCamera() {
        Vector3f camDir = cam.getDirection().mult(1.4f).mult(mapControl.getDude().getSpeedModifier());
        Vector3f camLeft = cam.getLeft().mult(mapControl.getDude().getSpeedModifier());
        camDir.y = 0;
        camLeft.y = 0;
       // viewDirection.set(camDir);
        mapControl.getDude().setWalkDir(new Vector3f(0, 0, 0));
        if (IO.left) {
            mapControl.getDude().moveTowards(camLeft.mult(this.globalTpf));
        } else
        if (IO.right) {
            mapControl.getDude().moveTowards(camLeft.negate().mult(this.globalTpf));
        }  
        if (IO.up) {
            mapControl.getDude().moveTowards(camDir.mult(this.globalTpf));
        } else
        if (IO.down) {
            mapControl.getDude().moveTowards(camDir.negate().mult(this.globalTpf));
        }
        if (IO.rotateLeft) {
            myCamera.acelerate(7);
        } else if(IO.rotateRight)
            myCamera.acelerate(9);
        else
            myCamera.deacelerate();
        
        //debug.setLocalTranslation(mapControl.getDude().getLookDir());
    }
    
    //@Override
    //public void simpleRender(RenderManager rm) {
    //    //TODO: add render code
    //}
    
    public void onAction(String name, boolean pressed, float tpf){
        if(name.substring(0,4).equals("MOVE")) { // move.coisa
            if(mapControl.getDude().getReadingSignId()!=null) {
                mapControl.getDude().setReadingSignId(null);
                signs.close();
            }
            if(name.substring(5).equals("4"))
                IO.left = pressed;
            else if(name.substring(5).equals("2"))
                IO.down = pressed;
            else if(name.substring(5).equals("6"))
                IO.right = pressed;
            else if(name.substring(5).equals("8"))
                IO.up = pressed;
            else if(name.substring(5).equals("7"))
                IO.rotateLeft = pressed;
            else if(name.substring(5).equals("9"))
                IO.rotateRight = pressed;
        }
    }
    
    public void setupFilters(){
        if (renderer.getCaps().contains(Caps.GLSL100)){
            fpp=new FilterPostProcessor(assetManager);
            //fpp.setNumSamples(4);
            CartoonEdgeFilter toon=new CartoonEdgeFilter();
            toon.setEdgeColor(ColorRGBA.Black);
            fpp.addFilter(toon);
            viewPort.addProcessor(fpp);
        }
    }
    
    public EventHandler getEventHandler() { return this.eventHandler; }
    
}
